﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using PoolGame2.Physics;
/*
    Action              Keyboard            Xbox Controller
    ------------------  ---------------     ------------------------------------------
    Move cam up         Up arrow            Right Thumbstick Up
    Move cam down       Down arrow          Right Thumbstick Down
    Move cam right      Right arrow         Right Thumbstick Right
    Move cam left       Left arrow          Right Thumbstick Left
    ------------------  ---------------     ------------------------------------------
    Move cue tip up     Shift + Up arrow    Right Shoulder + Right Thumbstick Up
    Move cue tip down   Shift + Down arrow  Right Shoulder + Right Thumbstick Down
    Move cue tip right  Shift + Right arrow Right Shoulder + Right Thumbstick Right
    Move cue tip left   Shift + Left arrow  Right Shoulder + Right Thumbstick Left
    ------------------  ---------------     ------------------------------------------
    Zoom in             W                   Left Thumbstick Up
    Zoom out            S                   Left Thumbstick Down
    Build up power      Hold down spacebar  Right Trigger (hold down)
    Take shot           Release Spacebar    Release Right Trigger
    Tracking on/off     T                   Y button
    Topdown on/off      Alt Left            Left Shoulder button
    ------------------  ---------------     ------------------------------------------
    Menu Yes            Enter               A
    Menu No             Esc                 B    
 */
namespace PoolGame2.Controls
{
    public abstract class GameControls : GameComponent
    {

        public List<IGameControlListener> listeners;

        KeyboardState previousKeyBoardState;
        GamePadState previousGamePadState;

        KeyboardState currentKeyBoardState;
        protected GamePadState currentGamePadState;

        bool inMenu = false;

        
            
        // Keyboard control buttons
        public GameControls(PoolGame game) : base(game)
        {
            this.listeners = new List<IGameControlListener>();
        
        }

        public abstract void PollController(GameTime gameTime);


        public void addListener(IGameControlListener listener)
        {
            this.listeners.Add(listener);
        }

        protected void NotifyListeners(List<GameControlAction> actions) {
            foreach (IGameControlListener listener in listeners) {
                listener.GameControlPerformed(actions);
            }
        }

#if XBOX
        bool XboxController = true;
#else
        bool XboxController = false;
#endif

        public bool InMenu
        {
            get { return inMenu; }
            set { inMenu = value; }
        }


        public void Update()
        {
            if (XboxController)
            {
                previousGamePadState = currentGamePadState;
                currentGamePadState = GamePad.GetState(PlayerIndex.One);
            }
            else
            {
                previousKeyBoardState = currentKeyBoardState;
                currentKeyBoardState = Keyboard.GetState();
            }

        }

        /**
         * MENU CONTROLS
         */
        public bool MenuScrollUp() {
            if (XboxController)            
                return (previousGamePadState.ThumbSticks.Left.Y == 0.0f && currentGamePadState.ThumbSticks.Left.Y > 0.0f);            
            else            
                return IsKeyPressed(Keys.Up);            
        }

        public bool MenuScrollDown() {
            if (XboxController)            
                return (previousGamePadState.ThumbSticks.Left.Y == 0.0f && currentGamePadState.ThumbSticks.Left.Y < 0.0f);
            else            
                return IsKeyPressed(Keys.Down);            
        }

        public bool MenuBackAction() {
            if (XboxController)
                return IsKeyPressed(Buttons.B);            
            else             
                return IsKeyPressed(Keys.Escape);            
        }

        public bool MenuForwardAction() { 
            if (XboxController) 
                return (IsKeyPressed(Buttons.A));            
            else
                return IsKeyPressed(Keys.Enter);
        }

        /**
         * PLAYING CONTROLS 
         */
        public bool PlayerTakingShot() {
            if (XboxController)            
                return (currentGamePadState.Triggers.Right > 0.0f);            
            else            
                return IsKeyPressed(Keys.Space);            
        }

        public bool TakeShot() {
            if (XboxController)
                return (previousGamePadState.Triggers.Right > 0.0f && currentGamePadState.Triggers.Right == 0.0f);            
            else
                return IsKeyReleased(Keys.Space);            
        }

        public Vector3 MoveCueTip(Vector3 currentPosition) {
            Vector3 newPosition = currentPosition;
            if (XboxController)
            {
                if (currentGamePadState.IsButtonDown(Buttons.RightShoulder)) {
                    newPosition.Y += currentGamePadState.ThumbSticks.Right.Y * 0.02f;
                    newPosition.X += currentGamePadState.ThumbSticks.Right.X * 0.02f;
                }
            }
            else
            {
                if (IsKeyDown(Keys.LeftShift) || IsKeyDown(Keys.RightShift)) {
                    if (IsKeyDown(Keys.Up)) { newPosition.Y += 0.1f; }
                    if (IsKeyDown(Keys.Down)) { newPosition.Y -= 0.1f; }
                    if (IsKeyDown(Keys.Right)) { newPosition.X -= 0.1f; }
                    if (IsKeyDown(Keys.Left)) { newPosition.X += 0.1f; }
                }
            }
            newPosition.X = MathHelper.Clamp(newPosition.X ,- (PhysicsConstants.DEFAULT_RADIUS - 0.1f), (PhysicsConstants.DEFAULT_RADIUS - 0.1f));
            newPosition.Y = MathHelper.Clamp(newPosition.Y ,- (PhysicsConstants.DEFAULT_RADIUS - 0.1f), (PhysicsConstants.DEFAULT_RADIUS - 0.1f));

            return newPosition;
        }
        /**
         * CAMERA CONTROLS
         */
        public Vector3 UpdateCameraPosition(Vector3 currentPosition)
        {

            // Translational controls

            if (XboxController)
            {
                currentPosition.Z += currentGamePadState.ThumbSticks.Left.Y;// *0.5f;
                currentPosition.X -= currentGamePadState.ThumbSticks.Left.X;// *0.5f;
            }
            else
            {
                if (IsKeyDown(Keys.W)) { currentPosition.Z += 1f; }
                if (IsKeyDown(Keys.S)) { currentPosition.Z -= 1f; }
                if (IsKeyDown(Keys.A)) { currentPosition.X += 1f; }
                if (IsKeyDown(Keys.D)) { currentPosition.X -= 1f; }
            }
            return currentPosition;
        }

        public float UpdateCameraYaw(float currentYaw)
        {
            if (XboxController)
            {
                if (currentGamePadState.IsButtonUp(Buttons.RightShoulder))
                {
                    currentYaw -= currentGamePadState.ThumbSticks.Right.X * 0.02f;
                }
            }
            else
            {
                if (IsKeyUp(Keys.LeftShift) && IsKeyUp(Keys.RightShift))
                {
                    if (IsKeyDown(Keys.Left)) { currentYaw += 0.02f; }
                    if (IsKeyDown(Keys.Right)) { currentYaw -= 0.02f; }
                }
            }
            return currentYaw;
        }

        public float UpdateCameraPitch(float currentPitch)
        {
            if (XboxController)
            {
                if (currentGamePadState.IsButtonUp(Buttons.RightShoulder))
                {
                    currentPitch -= currentGamePadState.ThumbSticks.Right.Y * 0.02f;
                }
            }
            else
            {
                if (IsKeyUp(Keys.LeftShift) && IsKeyUp(Keys.RightShift))
                {
                    if (IsKeyDown(Keys.Up)) { currentPitch -= 0.02f; }
                    if (IsKeyDown(Keys.Down)) { currentPitch += 0.02f; }
                }
            }
            return currentPitch;
        }

        public float UpdateCameraLookAtOffset(float currentOffset)
        {
            if (XboxController)
            {
                currentOffset -= currentGamePadState.ThumbSticks.Left.Y;// *0.5f;
            }
            else
            {
                if (IsKeyDown(Keys.W)) { currentOffset -= 3f; }
                if (IsKeyDown(Keys.S)) { currentOffset += 3f; }
            }
            return currentOffset;
        }

        public float UpdateCameraY(float currentY)
        {
            //if (XboxController)
            //{
            //    currentOffset -= currentGamePadState.ThumbSticks.Left.Y;// *0.5f;
            //}
            //else
            //{
            if (IsKeyDown(Keys.R)) { currentY += 1f; }
            if (IsKeyDown(Keys.F)) { currentY -= 1f; }
            //}
            return currentY;
        }

        public Vector3 UpdateCameraLookAtRotation(Vector3 currentRotation)
        {
            if (XboxController)
            {
                if (currentGamePadState.IsButtonUp(Buttons.RightShoulder))
                {
                    currentRotation.Y -= currentGamePadState.ThumbSticks.Right.X * 0.02f;
                    currentRotation.X -= currentGamePadState.ThumbSticks.Right.Y * 0.02f;
                }
            }
            else
            {
                if (IsKeyUp(Keys.LeftShift) && IsKeyUp(Keys.RightShift))
                {
                    if (IsKeyDown(Keys.Left)) { currentRotation.Y += 0.02f; }
                    if (IsKeyDown(Keys.Right)) { currentRotation.Y -= 0.02f; }
                    if (IsKeyDown(Keys.Up)) { currentRotation.X -= 0.02f; }
                    if (IsKeyDown(Keys.Down)) { currentRotation.X += 0.02f; }
                }
            }
            return currentRotation;

        }
        public void SwitchCamera(bool forward) {


        }

        public bool SwitchToNoClip(bool currentNoClipState)
        {
            //if (XboxController)
            //{
            //    if (previousGamePadState.Buttons.LeftShoulder == ButtonState.Released &&
            //        currentGamePadState.Buttons.LeftShoulder == ButtonState.Pressed)
            //    {
            //        return !currentTopDownState;
            //    }
            //    else
            //    {
            //        return currentTopDownState;
            //    }
            //}
            //else
            //{
                if (IsKeyPressed(Keys.Q))
                    return !currentNoClipState;
                else
                    return currentNoClipState;
            //}

        }
        /**
         * MISC
         */
        public bool IsKeyPressed(Keys key)
        {
            return (previousKeyBoardState.IsKeyUp(key) && currentKeyBoardState.IsKeyDown(key));
        }

        public bool IsKeyReleased(Keys key)
        {
            return (previousKeyBoardState.IsKeyDown(key) && currentKeyBoardState.IsKeyUp(key));
        }

        public bool IsKeyDown(Keys key)
        {
            return (currentKeyBoardState.IsKeyDown(key));
        }

        public bool IsKeyUp(Keys key)
        {
            return (currentKeyBoardState.IsKeyUp(key));
        }

        /// <summary>
        ///  
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool IsKeyPressed(Buttons key)
        {
            return (previousGamePadState.IsButtonUp(key) && currentGamePadState.IsButtonDown(key));
        }

        public bool IsKeyReleased(Buttons key)
        {
            return (previousGamePadState.IsButtonDown(key) && currentGamePadState.IsButtonUp(key));
        }

        public bool IsKeyDown(Buttons key)
        {
            return (currentGamePadState.IsButtonDown(key));
        }

        public bool IsKeyUp(Buttons key)
        {
            return (currentGamePadState.IsButtonUp(key));
        }
    }
}
